package cate.game.role.history;

import cate.common.game.GameCollection;
import cate.common.table.task.row.HistoryRow;
import cate.game.role.Role;
import cate.game.role.RolePart;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Document(collection = GameCollection.NAME_ROLE_HISTORY)
public class RoleHistory extends RolePart {

    @JsonIgnore
    @Transient
    public HistoryAction action = new HistoryAction(this);

    @NoteField(value = "永久的历史记录")
    public List<HistoryItem> items;

    @NoteField(value = "已开启的功能")
    public Set<Integer> enableCodes;

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        checkOpen();
    }

    public RoleHistory() {
    }

    public RoleHistory(Role role) {
        super(role);
    }

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (items == null) {
            items = new ArrayList<>();
        }
        if (enableCodes == null) {
            enableCodes = new HashSet<>();
        }
    }

    /**
     * 获取历史记录
     */
    public HistoryItem getItem(int event, int param) {
        for (HistoryItem item : items) {
            if (item.key.eq(event, param)) {
                return item;
            }
        }
        return null;
    }

    /**
     * 记录历史值
     *
     * @param event 事件类型
     * @param param 参数
     * @param value 值
     * @param add   是否累加
     */
    public void record(int event, int param, long value, boolean add) {
        HistoryItem old = getItem(event, param);
        HistoryItem latest = null;
        if (old == null) {
            HistoryRow hisTpl = role.getGame().table.task.history.find(event, param);
            if (hisTpl != null) {
                latest = new HistoryItem(event, hisTpl.param, value);
                items.add(latest);
            }
        } else {
            if (add) {
                latest = old;
                latest.setValue(value, true);
            } else {
                if (value != old.cur) {
                    latest = old;
                    latest.setValue(value, false);
                }
            }
        }
    }

    public void checkOpen() {
        int worldLevel = role.getGame().cross.getWorldLevel();
        Set<Integer> codes = role.getGame().table.common.funcEnable.getList().stream().
                filter(e -> !enableCodes.contains(e.id)
                        && role.getGame().table.common.funcEnable.isEnable(
                        role.getBase().level,
                        role.getBase().vip,
                        role.getGame().getOpenDay(),
                        worldLevel,
                        e.id,
                        role.getFarm().adventure.getAdventurePassedNum()
                ).ok()).map(e -> e.id).collect(Collectors.toSet());
        codes.forEach(e -> {
            enableCodes.add(e);
            role.getHistory().action.newFuncOpen(e);
        });
    }
}
